import json
import random
import re
import time

from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import HttpResponse, HttpResponseRedirect
from django.core.cache import cache
import uuid
import requests

from user import models, userser
from utils.captcha import CaptchaGenerator
from utils.myRedis import myRedis
from utils.send import send_message
from utils.JWTTool import jwtTool
from django.views import View
from django.http import JsonResponse
from io import BytesIO
import base64
import qrcode
from user.models import User, Role


class CaptchaView(APIView):
    def get(self, request):
        # 生成验证码
        captcha = CaptchaGenerator()
        code, image_buffer = captcha.get_captcha()

        # 生成唯一标识
        captcha_key = request.query_params.get('captcha_key')

        # 将验证码保存到redis缓存，设置有效期2分钟
        myRedis.set(captcha_key, code, 120)

        # 返回验证码图片和标识
        response = HttpResponse(image_buffer, content_type='image/png')
        response['X-Captcha-Key'] = captcha_key
        return response


class SendCode(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        captcha_key = request.data.get('captcha_key')
        icode = request.data.get("icode")
        if not phone:
            return Response({'code': 400, 'msg': '手机号不能为空'})
        re_phone = re.match(r'^1[3-9]\d{9}$', phone)
        if not re_phone:
            return Response({'code': 400, 'msg': '手机号格式错误'})
        if not icode:
            return Response({'code': 400, 'msg': '验证码不能为空'})
        # 从redis中获取uuid对应的图片验证码
        r_icode = myRedis.get(captcha_key)
        if not r_icode:
            return Response({'code': 400, 'msg': '图片验证码已过期'})
        elif r_icode != icode:
            return Response({'code': 400, 'msg': '图片验证码错误'})
        else:
            myRedis.delete(captcha_key)

        code = random.randint(1000, 9999)
        re_code = send_message(phone, code)
        res_code = json.loads(re_code)
        if res_code['statusCode'] == '000000':
            myRedis.set(phone, code, 120)
            return Response({'code': 200, 'msg': '发送成功'})
        else:
            return Response({'code': 400, 'msg': '发送失败'})


class LoginByCode(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        code = request.data.get('code')
        if not phone:
            return Response({'code': 400, 'msg': '手机号不能为空'})
        if not code:
            return Response({'code': 400, 'msg': '验证码不能为空'})
        re_phone = re.match(r'^1[3-9]\d{9}$', phone)
        print("这是手机号：", phone,"验证码:", code)

        if not re_phone:
            return Response({'code': 400, 'msg': '手机号格式错误'})
        user = models.User.objects.filter(phone=phone).first()
        print("这是用户,他还在：", user)
        if not user:
            ser = userser.UserSerializer(data=request.data)
            if ser.is_valid():
                ser.save()
                r_ser = userser.ResumeSerializer(data=request.data)
                if r_ser.is_valid():
                    r_ser.save()
                    token = jwtTool.generate_token(ser.data.id)
                    return Response({'code': 200, 'msg': '注册成功', 'data': ser.data, 'token': token})
                return Response({'code': 400, 'msg': '注册失败'})
            return Response({'code': 400, 'msg': '注册失败'})

        r_code = myRedis.get(phone)
        print("验证码拿到了", r_code)
        if r_code != code:
            return Response({'code': 400, 'msg': '验证码错误'})
        token = jwtTool.generate_token(user.id)
        pyload = jwtTool.decode_token(token)
        pyload['exp'] = pyload['exp'] + 60 * 60 * 24
        retoken = jwtTool.encode(pyload)
        return Response(
            {'code': 200, 'msg': '登录成功', 'data': {'token': token, 'retoken': retoken, "userid": user.id}})


class Retoken(APIView):
    def get(self, request):
        retoken = request.query_params.get('retoken')
        pyload = jwtTool.decode_token(retoken)
        pyload['exp'] = pyload['exp'] + 60 * 60 * 24 * 7
        token = jwtTool.encode(pyload)
        pyload = jwtTool.decode_token(token)
        pyload['exp'] = pyload['exp'] + 60 * 60 * 24
        retoken = jwtTool.encode(pyload)
        return Response(
            {'code': 200, 'data': {'token': token, 'retoken': retoken}})


# ========== QQ模拟登录相关视图 ==========

class QQLoginView(View):
    """QQ模拟登录 - 生成二维码"""

    def get(self, request):
        login_success_url = "http://127.0.0.1:8000/user/qq-success/"
        qr = qrcode.QRCode(box_size=10, border=4)
        qr.add_data(login_success_url)
        qr.make(fit=True)
        img = qr.make_image(fill_color="black", back_color="white")
        buffer = BytesIO()
        img.save(buffer, format="PNG")
        img_str = base64.b64encode(buffer.getvalue()).decode()
        return JsonResponse({
            "qr_code": f"data:image/png;base64,{img_str}",
            "login_url": login_success_url,
            "msg": "QQ登录二维码已生成"
        })


class QQSuccessView(View):
    """QQ模拟登录成功页面"""

    def get(self, request):
        default_role = Role.objects.first()
        if not default_role:
            return JsonResponse({
                "error": "系统错误",
                "msg": "请先在后台创建至少一个角色"
            }, status=500)
        mock_qq_user = {
            'openid': f'qq_openid_{random.randint(10000, 99999)}',
            'nickname': f'QQ用户{random.randint(1000, 9999)}',
            'avatar': 'https://qlogo.cn/qqapp/102795359/default/100'
        }
        user, created = User.objects.get_or_create(
            phone=mock_qq_user['openid'],
            defaults={
                'role': default_role
            }
        )
        # 生成一个假的token
        fake_token = str(uuid.uuid4())
        user_info = {
            "userid": user.id,
            "username": mock_qq_user['nickname'],
            "openid": mock_qq_user['openid'],
            "nickname": mock_qq_user['nickname'],
            "avatar": mock_qq_user['avatar']
        }
        html_content = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>QQ登录成功</title>
            <style>
                body {{
                    font-family: Arial, sans-serif;
                    text-align: center;
                    padding: 50px;
                    background-color: #f0f8ff;
                    margin: 0;
                }}
                .success-container {{
                    max-width: 400px;
                    margin: 0 auto;
                    padding: 30px;
                    background-color: white;
                    border-radius: 8px;
                    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                }}
                .success-icon {{
                    color: #28a745;
                    font-size: 48px;
                    margin-bottom: 20px;
                }}
                .user-info {{
                    margin: 20px 0;
                    padding: 15px;
                    background-color: #f8f9fa;
                    border-radius: 4px;
                }}
                .avatar {{
                    width: 60px;
                    height: 60px;
                    border-radius: 50%;
                    margin-bottom: 10px;
                }}
                .close-btn {{
                    background-color: #6c757d;
                    color: white;
                    padding: 10px 20px;
                    border: none;
                    border-radius: 4px;
                    cursor: pointer;
                    margin-top: 20px;
                }}
                .close-btn:hover {{
                    background-color: #5a6268;
                }}
            </style>
        </head>
        <body>
            <div class="success-container">
                <div class="success-icon">✓</div>
                <h2>QQ登录成功！</h2>
                <div class="user-info">
                    <img src="{user_info['avatar']}" alt="头像" class="avatar">
                    <p><strong>用户名：</strong>{user_info['nickname']}</p>
                    <p><strong>OpenID：</strong>{user_info['openid']}</p>
                </div>
                <p>正在自动关闭页面...</p>
                <button class="close-btn" onclick="closeWindow()">关闭页面</button>
            </div>

            <script>
                localStorage.setItem('qq_token', '{fake_token}');
                localStorage.setItem('qq_user_info', JSON.stringify({user_info}));
                setTimeout(() => {{
                    closeWindow();
                }}, 3000);

                function closeWindow() {{
                    try {{
                        window.close();
                    }} catch (e) {{
                        // 如果无法关闭，显示提示
                        document.body.innerHTML = '<div style="text-align:center;padding:50px;"><h2>登录成功！</h2><p>可以关闭此页面了。</p></div>';
                    }}
                }}
            </script>
        </body>
        </html>
        """

        return HttpResponse(html_content, content_type='text/html')



# ========== 钉钉第三方登录 ==========
# 获取url地址跳转钉钉授权页面->钉钉回调首页->获取code->获取用户token->获取用户信息->
# 1.点击获取钉钉登录URL  点击钉钉图片跳转到登录授权页面
class DDGetUrl(APIView):
    def get(self,request):
        # 生成随机状态码，防止CSRF攻击
        state = str(uuid.uuid4())
        request.session['dingtalk_state'] = state

        # 构建钉钉授权URL
        redirect_uri = "http://localhost:8000/user/dd_callback/"       # 回调地址-下一个接口
        # 钉钉应用配置
        DINGTALK_APPID = 'dinglyrgo3vzh4tgz09p'  # 钉钉开放平台应用ID  APPKey

        url=f"https://login.dingtalk.com/oauth2/auth?redirect_uri={redirect_uri}&response_type=code&client_id={DINGTALK_APPID}&scope=openid corpid&state={state}&prompt=consent"
        # url=f"https://login.dingtalk.com/oauth2/auth?redirect_uri=http://localhost:8000/user/callback/&response_type=code&client_id=dinglyrgo3vzh4tgz09p&scope=openid corpid&state=state&prompt=consent"
        return Response({"code":200,"msg":'获取成功！',"url":url})

# 2.回调接口-获取用户信息。
# 当用户同意授权之后，钉钉会返回code参数 重定向到回调地址，通过code参数获取用户信息access_token
class DDCallback(APIView):
    def get(self,request):
        # 获取前端参数code
        code=request.query_params.get('code')
        if not code:
            return Response('/?error=钉钉授权失败')
        url="https://api.dingtalk.com/v1.0/oauth2/userAccessToken"

        # 根据code获取用户accessToken
        data = {
            "clientId": "dinglyrgo3vzh4tgz09p",
            "clientSecret": "qv3DPWXqcxr0mSv9B6S2eaExQth7TdxMBzSd4gdemXEKlEPJaJ4th7jtb4ubwwdc",
            "code": code,
            "grantType": "authorization_code"
        }
        response = requests.post(url, json=data).json()
        print("钉钉返回：", response)  # 调试用

        # 使用 code 向钉钉服务器请求 accessToken
        if "accessToken" not in response:
            return Response({"code": 500, "msg": "钉钉授权失败", "detail": response})
        accessToken = response["accessToken"]
        # uid = response["openId"]

        # 根据accessToken获取用户信息
        user_info_url = "https://api.dingtalk.com/v1.0/contact/users/me"
        headers = {"x-acs-dingtalk-access-token": accessToken}
        user_info = requests.get(user_info_url, headers=headers).json()
        print("钉钉用户信息：", user_info)

        if "openId" not in user_info:
            return Response({"code": 500, "msg": "获取钉钉用户信息失败", "detail": user_info})

        uid = user_info["openId"]
        name = user_info.get('nick')
        phone = user_info.get('mobile')

        # 登录 获取第三方登录表 和 用户表
        third=models.ThirdLogin.objects.filter(oauth_id=uid,style='dingding').first()      #oauth_id第三方登录id
        if not third:
            # 写入用户表  手机号用户存在直接绑定  手机号不存在则创建用户
            user=models.User.objects.filter(phone=phone).first()
            if not user:
                userinfo={
                    "phone": phone,
                    "role": 1
                }
                u=userser.UserSerializer(data=userinfo)
                if u.is_valid():
                    user=u.save()
                else:
                    print(u.errors)  # 打印验证错误信息
                    return Response({"code": 500, "msg": '用户创建失败', "errors": u.errors})
            # 写入第三方登录表
            thinfo={
                "oauth_id": uid,
                "style": "dingding",
                "token": accessToken,
                "userid": user.id
            }
            t=userser.ThirdLoginSerializer(data=thinfo)
            if t.is_valid():
                t.save()
            else:
                return Response({"code": 500, "msg": '第三方登录创建失败'})
        else:
            user=third.userid
            user.token=accessToken
            user.save()

        # 生成jwt token并返回前端
        payload = {"user_id": user.id}
        token = jwtTool.generate_token(payload)
        payload["exp"] = int(time.time() + 60 * 60 * 24 * 2)
        refreshToken = jwtTool.generate_token(payload)
        # 这里改为重定向
        redirect_url = f"http://localhost:5173/home/?token={token}&retoken={refreshToken}&userid={user.id}"
        return HttpResponseRedirect(redirect_url)